#include "BaseType.h"
#include "Tracer.h"
#include "StrUtil.h"
using namespace std;
using namespace libemb;

/**
 * 中介者模式：
 * 1.用一个中介者对象封装一系列的对象交互，中介者使各对象不需要显式地相互引用，从而使耦合松散。
 * 适用场景：
 * 1.
 * 2.
 **/

//抽象中介者
class Mediator{
DECL_CLASSNAME(Mediator)
public:
    virtual void showBoyToGirls(std::string msg)=0;
    virtual void showGirlToBoys(std::string msg)=0;
};

//抽象类
class Person{
DECL_CLASSNAME(Person)
public:
    Person(Mediator* mediator,std::string name):m_mediator(mediator),m_name(name){};
    virtual void findFriend()=0;
    void sayHello()
    {
        TRACE_INFO_CLASS("Hello, I am %s, Nice to meet you!",CSTR(m_name));
    }
protected:
    Mediator* m_mediator;
    std::string m_name;
};

/* 具体类：女孩 */
class Girl:public Person{
DECL_CLASSNAME(Girl)
public:
    Girl(Mediator* mediator,std::string name):Person(mediator,name){};
    void findFriend() override
    {
        m_mediator->showGirlToBoys(StrUtil::stringFormat("Hi, I am %s, is there any girl to be my friend?",CSTR(m_name)));
    }
};

/* 具体类：男孩 */
class Boy:public Person{
DECL_CLASSNAME(Boy)
public:
    Boy(Mediator* mediator,std::string name):Person(mediator,name){};
    void findFriend() override
    {
        m_mediator->showBoyToGirls(StrUtil::stringFormat("Hi, I am %s, is there any girl to be my friend?",CSTR(m_name)));
    }
};

/* 具体中介者 */
class MatchMaker: public Mediator{
DECL_CLASSNAME(MatchMaker)
public:
    void registerBoy(Boy* boy)
    {
        m_boys.push_back(boy);
    }
    void registerGirl(Girl* girl)
    {
        m_girls.push_back(girl);
    }

    /* 封装男孩子跟所有女孩子打招呼的交互过程 */
    void showBoyToGirls(std::string msg) override
    {
        TRACE_INFO_CLASS("MatchMaker: Hi, girls! There is a boy who wanna a girl friend.");
        TRACE_INFO_CLASS("Boy       : %s",CSTR(msg));
        for(auto girl: m_girls)
        {
            girl->sayHello();
        }
    }

    /* 封装女孩子跟所有男孩子打招呼的交互过程 */
    void showGirlToBoys(std::string msg) override
    {
        TRACE_INFO_CLASS("MatchMaker: Hi, boys! There is a girl who wanna a boy friend.");
        TRACE_INFO_CLASS("Girl       : %s",CSTR(msg));
        for(auto boy: m_boys)
        {
            boy->sayHello();
        }
    }
private:
    std::vector<Girl*> m_girls;
    std::vector<Boy*> m_boys;
};



int main()
{
    Tracer::getInstance().setLevel(TRACE_LEVEL_DBG);
	Tracer::getInstance().addSink(std::make_shared<STDSink>()).start();

    MatchMaker meipo;
    Boy jack(&meipo,"Jack");
    Boy jim(&meipo,"Jim");
    Girl lucy(&meipo,"Lucy");
    Girl lily(&meipo,"Lily");

    //所有人都到红娘那里注册一下
    meipo.registerBoy(&jack);
    meipo.registerBoy(&jim);
    meipo.registerGirl(&lucy);
    meipo.registerGirl(&lily);

    //Jack想找女朋友,只需要跟红娘说一声,红娘就把Girl介绍给他了
    jack.findFriend();

    //Lucy想找男朋友,也只需要跟红娘说一声,红娘就把所有Boy都介绍给她
    lucy.findFriend();
    return RC_OK;
}